package cn.wsh.basic.interceptor;

import cn.wsh.basic.jwt.JwtUtils;
import cn.wsh.basic.jwt.LoginData;
import cn.wsh.basic.jwt.Payload;
import cn.wsh.basic.jwt.RsaUtils;
import cn.wsh.org.mapper.EmployeeMapper;
import cn.wsh.system.anno.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.security.PublicKey;
import java.util.List;

@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private EmployeeMapper employeeMapper;

    @Value("${jwt.rsa.pub}")//SEL
    private String pubKey;


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.获取请求头中的token
        String jwtToken = request.getHeader("U-TOKEN");
        //2.校验  token不能为空
        if (!StringUtils.isEmpty(jwtToken)) {
            //3.解密jwtToken 得到对应的登录信息
            //获取公钥
            PublicKey publicKey = RsaUtils.getPublicKey(JwtUtils.class.getClassLoader().getResource(pubKey).getFile());
            Payload<LoginData> payload = JwtUtils.getInfoFromToken(jwtToken, publicKey, LoginData.class);
            //3.1 拿不到  登录失效或者是个瓦token 阻止放行
            if (payload != null) {
                //3.2 拿到了  刷新token过期时间，方案待定
                /*if(payload.getExpiration().after(new Date(System.currentTimeMillis()))){
                    //刷新过期时间....
                 }*/
                //还需要看当前这个人是否有权限访问资源
                LoginData loginData = payload.getLoginData();
                if (loginData.getUser() != null) {
                    //1.如果是前端用户 user ，不需要校验任何权限，直接放行即可
                    return true;//放行
                }
                //2.如果是后端员工employee来操作的时候，才需要校验资源的访问权限
                //2.1 哪些请求需要校验权限 （答：打了自定义注解PreAuthorize权限的方法）
                HandlerMethod handlerMethod = (HandlerMethod) handler;
                PreAuthorize preAuthorize = handlerMethod.getMethodAnnotation(PreAuthorize.class);
                //3.判断preAuthorize 是否有值
                if (preAuthorize == null) {
                    //3.2 没有，放行  公共资源不需要校验权限
                    return true;
                }
                //3.1 有，校验是否有权限访问
                String sn = preAuthorize.value();//需要校验当前登录人，是否有权限访问该资源
                //查询出当前登录人所拥有的权限
                List<String> ownPermissions = loginData.getPermissions();//从jwt中解析得到权限信息
                if (ownPermissions.contains(sn)) {
                    return true;//终于有权限访问了
                }
                //告诉他没有权限，请他去联系管理员
                response.setCharacterEncoding("UTF-8");
                response.setContentType("application/json;charset=utf-8");
                PrintWriter writer = response.getWriter();
                writer.print("{\"success\":false,\"message\":\"noPermission\"}");
                writer.flush();
                writer.close();
                return false;//阻止放行
            }
        }
        //这里不能直接报错，需要返回AjaxResult响应给前端，不能直接返回AjaxResult
        // 应该将AjaxResult 写入到response的流中
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.print("{\"success\":false,\"message\":\"noLogin\"}");
        writer.flush();
        writer.close();
        return false;//阻止放行
    }
/*
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.获取请求头中的token
        String token = request.getHeader("U-TOKEN");
        //2.校验  token不能为空
        if(!StringUtils.isEmpty(token)){
            //3.根据token的值，从redis中获取登录信息
            Object loginTmp = redisTemplate.opsForValue().get(token);
            //3.1 拿不到  登录失效或者是个瓦token 阻止放行
            if(loginTmp != null){
                //3.2 拿到了  刷新token过期时间，放行
                redisTemplate.opsForValue().set(
                        token,
                        loginTmp,
                        30,
                        TimeUnit.MINUTES
                );
                //还需要看当前这个人是否有权限访问资源
                Logininfo logininfo = (Logininfo) loginTmp;
                if(logininfo.getType().intValue() == 1){
                    //1.如果是前端用户 user ，不需要校验任何权限，直接放行即可
                    return true;//放行
                }
                //2.如果是后端员工employee来操作的时候，才需要校验资源的访问权限
                //2.1 哪些请求需要校验权限 （答：打了自定义注解PreAuthorize权限的方法）
                HandlerMethod handlerMethod = (HandlerMethod) handler;
                PreAuthorize preAuthorize = handlerMethod.getMethodAnnotation(PreAuthorize.class);
                //3.判断preAuthorize 是否有值
                if(preAuthorize == null){
                    //3.2 没有，放行  公共资源不需要校验权限
                    return true;
                }
                //3.1 有，校验是否有权限访问
                String sn = preAuthorize.value();//需要校验当前登录人，是否有权限访问该资源
                //查询出当前登录人所拥有的权限
                List<String> ownPermissions = employeeMapper.loadPerssionSnByLogininfoId(logininfo.getId());
                if(ownPermissions.contains(sn)){
                    return true;//终于有权限访问了
                }
                //告诉他没有权限，请他去联系管理员
                response.setCharacterEncoding("UTF-8");
                response.setContentType("application/json;charset=utf-8");
                PrintWriter writer = response.getWriter();
                writer.print("{\"success\":false,\"message\":\"noPermission\"}");
                writer.flush();
                writer.close();
                return false;//阻止放行
            }
        }
        //这里不能直接报错，需要返回AjaxResult响应给前端，不能直接返回AjaxResult
        // 应该将AjaxResult 写入到response的流中
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.print("{\"success\":false,\"message\":\"noLogin\"}");
        writer.flush();
        writer.close();
        return false;//阻止放行
    }
*/
}
